package org.apache.mina.protocol.dns;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.protocol.dns.messages.DnsMessage;
import org.apache.mina.protocol.dns.messages.ResourceRecord;
import org.apache.mina.protocol.dns.messages.ResponseCode;
import org.apache.mina.protocol.dns.protocol.DnsProtocolUdpCodecFactory;

class DnsHandler extends IoHandlerAdapter {

    private DnsResolver dnsManager;

    public DnsHandler(DnsResolver dnsManager) {
        this.dnsManager = dnsManager;
    }

    /* (non-Javadoc)
     * @see org.apache.mina.common.IoHandlerAdapter#sessionCreated(org.apache.mina.common.IoSession)
     */
    @Override
    public void sessionCreated(IoSession session) throws Exception {
        session.getFilterChain().addLast(
                "dns",
                new ProtocolCodecFilter(DnsProtocolUdpCodecFactory
                        .getInstance()));
    }

    /* (non-Javadoc)
     * @see org.apache.mina.common.IoHandlerAdapter#messageReceived(org.apache.mina.common.IoSession, java.lang.Object)
     */
    @Override
    public void messageReceived(IoSession session, Object message)
            throws Exception {
        DnsMessage dns = (DnsMessage) message;

        if (dns == null || dns.getAnswerRecords() == null
                || dns.getResponseCode() == ResponseCode.NAME_ERROR) {
            dnsManager.nameError(dns.getTransactionId());
            return;
        }

        List<InetAddress> addresses = new ArrayList<InetAddress>();
        int min_ttl = Integer.MAX_VALUE;

        for (ResourceRecord resource : dns.getAnswerRecords()) {
            switch (resource.getRecordType()) {
            case A:
            case A6:
                InetAddress addr = (InetAddress) resource
                        .get(DnsAttribute.IP_ADDRESS);

                addresses.add(addr);

                min_ttl = Math.min(min_ttl, resource.getTimeToLive());
                break;

            default:
                // Ignore
                break;
            }
        }

        dnsManager.receivedResponse(dns.getTransactionId(), addresses, min_ttl);
    }
}
